Présentation du projet
Membres Du Groupe:
Ait ADDI Abdelghafour Chouki Amina Matallah Mohamed Walid
Nous avons tous déjà réservé dans un hotel et annulé la réservation par la suite. Nous avons donc décidé de mener notre analyse sur Un Data set du site booking et essayer de prédire les annulations de résérvations .Le Web scrapping sur un tel site est sensible et nécéssite une demande au préalable c'est pour cela on a préféré de travailler sur un data set prêt.
pip install folium
pip install plotly.express
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import os
import scipy as sp
import warnings
import datetime
warnings.filterwarnings("ignore")
%matplotlib inline
def load_data(filepath):
return pd.read_csv(filepath)
data = load_data('hotel_bookings.csv')
data.head()
on imprime le nombre de chaque valeur unique dans chaque colonne du dataframe
def count_values_in_each_column(df):
for column in df.columns:
print(f"Column: {column}")
print(df[column].value_counts())
print()
count_values_in_each_column(data)
on imprime le nom des colonnes présentes dans le dataframe
def get_column_names(df):
return df.columns.tolist()
columns = get_column_names(data)
print(columns)
on imprime le type de chaque colonne
def get_data_types(df):
return {column: dtype.name for column, dtype in df.dtypes.iteritems()}
data_types = get_data_types(data)
print(data_types)
On vérifie s'il y'a des valeurs manquantes dans notre Dataframe
data.isnull().any()
data.isnull().sum()
effectivement il existe des valeurs manquantes dans notre dataframe, on remplacera ces par O dans le code qui suit.
data.fillna(0, inplace = True)
import seaborn as sns
plt.figure(figsize=(12,8))
sns.heatmap(data.isnull(), cbar=False, cmap='viridis')
plt.show()
le graphe ci dessus prouve qu'il n'ya plus de NA.
data.isnull().sum()
On crée un nouveau DataFrame country_wise_guests qui compte le nombre d'invités par pays qui n'ont pas annulé leur réservation.
pays_invités_nannulé= data[data['is_canceled'] == 0].groupby('country').size().reset_index(name='No of guests')
pays_invités_nannulé
import folium
from folium.plugins import HeatMap
import plotly.express as px
basemap = folium.Map()
guests_map = px.choropleth(pays_invités_nannulé, locations = pays_invités_nannulé['country'],
color = pays_invités_nannulé['No of guests'], hover_name = pays_invités_nannulé['country'])
guests_map.show()
import plotly.express as px
def plot_box(df, filter_col, filter_val, x, y, color):
filtered_df = df[df[filter_col] == filter_val]
fig = px.box(data_frame = filtered_df, x = x, y = y, color = color)
fig.show()
plot_box(data, 'is_canceled', 0, 'reserved_room_type', 'adr', 'hotel')
La graphe montre que le prix moyen par chambre dépend du type de chambre et de l'écart-type.
On crée deux nouveaux DataFrames, data_resort et data_city, qui représentent respectivement les réservations non annulées pour l'hôtel de type "Resort Hotel" et "City Hotel". Ensuite, on compte le nombre d'invités qui sont arrivés chaque mois à l'hôtel de type "Resort Hotel" et stocke ces informations dans un nouveau DataFrame, resort_guests.
data_resort = data.query("`hotel` == 'Resort Hotel' and `is_canceled` == 0")
data_city = data.query("`hotel` == 'City Hotel' and `is_canceled` == 0")
# Calcul du nombre de clients par mois pour les hôtels de type "Resort Hotel" et stockage du résultat dans un nouveau DataFrame.
resort_invité = pd.DataFrame(data_resort.groupby('arrival_date_month').size(), columns=['no of guests'])
resort_invité.reset_index(level=0, inplace=True)
resort_invité.rename(columns={'arrival_date_month':'month'}, inplace=True)
resort_invité
on compte le nombre d'invités qui sont arrivés chaque mois à l'hôtel de type "City Hotel" et stocke ces informations dans un nouveau DataFrame, city_guests.
# Calcul du nombre de clients par mois pour les hôtels de type "City Hotel" et stockage du résultat dans un nouveau DataFrame.
city_visiteur = pd.DataFrame(data_city.groupby('arrival_date_month').size(), columns=['no of guests'])
city_visiteur.reset_index(level=0, inplace=True)
city_visiteur.rename(columns={'arrival_date_month':'month'}, inplace=True)
city_visiteur
On crée un nouveau DataFrame, final_guests, qui est le résultat de la fusion des DataFrames resort_guests et city_guests sur la colonne 'month'.
# Fusionner les deux DataFrame sur le mois et renommer les colonnes
total_visiteurs = pd.concat([resort_invité.set_index('month'), city_visiteur.set_index('month')], axis=1, keys=['Resort', 'City'])
total_visiteurs.columns = ['nombre de clients dans resort', 'nombre de clients dans city hotel']
# Réinitialiser l'index pour que 'month' redevienne une colonne
total_visiteurs.reset_index(level=0, inplace=True)
total_visiteurs.rename(columns={'index':'month'}, inplace=True)
total_visiteurs
On le DataFrame final_guests en fonction de la colonne 'month'.
# Définition d'un ordre personnalisé pour les mois de l'année
months_order = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
# Conversion de la colonne 'month' en catégorie avec l'ordre personnalisé
total_visiteurs['month'] = pd.Categorical(total_visiteurs['month'], categories=months_order, ordered=True)
# Trier le DataFrame en fonction de l'ordre des mois
total_visiteurs = total_visiteurs.sort_values('month')
total_visiteurs
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(10,6))
sns.lineplot(x='month', y='nombre de clients dans resort', data=total_visiteurs, label='nombre de clients dans resort')
sns.lineplot(x='month', y='nombre de clients dans city hotel', data=total_visiteurs, label='nombre de clients dans city hotel ')
plt.title('Total nombre de clients par mois')
plt.xticks(rotation=45)
plt.legend(loc='upper right')
plt.show()
L'hôtel City accueille plus de visiteurs au printemps et en automne, lorsque les prix sont également les plus élevés. En juillet et en août, le nombre de visiteurs est moins élevé, bien que les prix soient plus bas. La fréquentation de l'hôtel Resort diminue légèrement de juin à septembre, période où les prix sont également les plus élevés. C'est en hiver que les deux hôtels accueillent le moins de visiteurs
data_3 = data.query("is_canceled == 0")
data_3.head()
On crée un nouveau DataFrame data_3 qui contient uniquement les lignes du DataFrame original data où la valeur de la colonne 'is_canceled' est égale à 0. En d'autres termes, data_3 ne contient que les réservations qui n'ont pas été annulées
data_3 = data_3.assign(total_nights = data_3['stays_in_weekend_nights'] + data_3['stays_in_week_nights'])
data_3.head()
duree = (data_3
.groupby(['total_nights', 'hotel'])
.size()
.reset_index(name='duree'))
duree
import matplotlib.pyplot as plt
duree_pivot = duree.pivot(index='total_nights', columns='hotel', values='duree')
duree_pivot.plot(kind='bar', stacked=False)
plt.xlabel('Total Nights')
plt.ylabel('duree')
plt.title('Total Nights vs duree pour chaque hotel')
plt.show()
import matplotlib.pyplot as plt
import numpy as np
plt.figure(figsize = (24, 12))
# Calcule la matrice de corrélation
corr = data.corr()
# Utilise matshow pour créer une matrice de couleur
plt.matshow(corr, cmap='RdBu')
# Crée une échelle de couleur
plt.colorbar()
# Ajoute des ticks pour chaque valeur et les fait pivoter pour une meilleure lisibilité
plt.xticks(np.arange(len(corr.columns)), corr.columns, rotation=90)
plt.yticks(np.arange(len(corr.columns)), corr.columns)
plt.show()
correlation = data.corr()['is_canceled'].abs().sort_values(ascending = False)
correlation
On fait une heatmap correlation pour voir comment les colonnes sont corréles ceci qui nous permettera de supprimer les colonnes qui ne corrélent pas avec la variable is canceled=0 qu'on juge inutile.
colonnes_inutiles = ['days_in_waiting_list', 'arrival_date_year', 'arrival_date_year', 'assigned_room_type', 'booking_changes',
'reservation_status', 'country', 'days_in_waiting_list']
data.drop(colonnes_inutiles, axis = 1, inplace = True)
cat_cols = [col for col in data.columns if data[col].dtype == 'O']
cat_cols
cat_df = data[cat_cols]
cat_df['reservation_status_date'] = pd.to_datetime(cat_df['reservation_status_date'])
cat_df['year'] = cat_df['reservation_status_date'].dt.year
cat_df['month'] = cat_df['reservation_status_date'].dt.month
cat_df['day'] = cat_df['reservation_status_date'].dt.day
cat_df.drop(['reservation_status_date','arrival_date_month'] , axis = 1, inplace = True)
cat_df['hotel'] = cat_df['hotel'].map({'Resort Hotel' : 0, 'City Hotel' : 1})
cat_df['meal'] = cat_df['meal'].map({'BB' : 0, 'FB': 1, 'HB': 2, 'SC': 3, 'Undefined': 4})
cat_df['market_segment'] = cat_df['market_segment'].map({'Direct': 0, 'Corporate': 1, 'Online TA': 2, 'Offline TA/TO': 3,
'Complementary': 4, 'Groups': 5, 'Undefined': 6, 'Aviation': 7})
cat_df['distribution_channel'] = cat_df['distribution_channel'].map({'Direct': 0, 'Corporate': 1, 'TA/TO': 2, 'Undefined': 3,
'GDS': 4})
cat_df['reserved_room_type'] = cat_df['reserved_room_type'].map({'C': 0, 'A': 1, 'D': 2, 'E': 3, 'G': 4, 'F': 5, 'H': 6,
'L': 7, 'B': 8})
cat_df['deposit_type'] = cat_df['deposit_type'].map({'No Deposit': 0, 'Refundable': 1, 'Non Refund': 3})
cat_df['customer_type'] = cat_df['customer_type'].map({'Transient': 0, 'Contract': 1, 'Transient-Party': 2, 'Group': 3})
cat_df['year'] = cat_df['year'].map({2015: 0, 2014: 1, 2016: 2, 2017: 3})
cat_df.head()
num_df = data.drop(columns = cat_cols, axis = 1)
num_df.drop('is_canceled', axis = 1, inplace = True)
num_df
num_df['adr'] = num_df['adr'].fillna(value = num_df['adr'].mean())
X = pd.concat([cat_df, num_df], axis = 1)
y = data['is_canceled']
missing_data_X = X.isnull().sum()
print(missing_data_X)
missing_data_y = y.isnull().sum()
print(missing_data_y)
# Gérer les valeurs manquantes et les valeurs infinies dans X
# Remplacer les valeurs infinies par NaN
X = X.replace([np.inf, -np.inf], np.nan)
# Remplacer les valeurs manquantes par la moyenne des autres valeurs
X = X.fillna(X.mean())
missing_data_X = X.isnull().sum()
print(missing_data_X)
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0,test_size=0.2)
from sklearn.linear_model import LogisticRegression
reg = LogisticRegression()
reg.fit(X_train,y_train)
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
y_pred_reg = reg.predict(X_test)
acc_reg = accuracy_score(y_test, y_pred_reg)
conf = confusion_matrix(y_test, y_pred_reg)
clf_report = classification_report(y_test, y_pred_reg)
train_score = reg.score(X_train, y_train) * 100
print("Classification Report:")
print(clf_report)
print("\nConfusion Matrix:")
print(conf)
print("\nTraining Score: {:.2f}%".format(train_score))
print("Accuracy Score of Logistic Regression: {:.2f}%".format(acc_reg * 100))
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
rfc=RandomForestClassifier()
rfc.fit(X_train,y_train)
from sklearn.metrics import confusion_matrix, classification_report, accuracy_score
y_pred_rfc = rfc.predict(X_test)
conf = confusion_matrix(y_test, y_pred_rfc)
clf = classification_report(y_test, y_pred_rfc)
score = accuracy_score(y_test, y_pred_rfc)
print("Confusion Matrix:\n", conf)
print("\nClassification Report:\n", clf)
print("Accuracy Score:", score)
from sklearn.tree import DecisionTreeClassifier
dtree = DecisionTreeClassifier(max_depth=6, random_state=123,criterion='entropy')
dtree.fit(X_train,y_train)
from sklearn.metrics import confusion_matrix, classification_report, accuracy_score
y_pred_dtree = dtree.predict(X_test)
conf = confusion_matrix(y_test, y_pred_dtree)
clf = classification_report(y_test, y_pred_dtree)
score = accuracy_score(y_test, y_pred_dtree)
print("Confusion Matrix:\n", conf)
print("\nClassification Report:\n", clf)
print("Accuracy Score:", score)
import seaborn as sns
import matplotlib.pyplot as plt
# Calculer les scores d'exactitude pour chaque méthode
acc_reg = accuracy_score(y_test, y_pred_reg)
acc_rfc = accuracy_score(y_test, y_pred_rfc)
acc_dtc = accuracy_score(y_test, y_pred_dtree)
# Créer un DataFrame pour stocker les méthodes et les scores d'exactitude
data = {'Method': ['Logistic Regression', 'Random Forest Classifier', 'Decision Tree Classifier'],
'Accuracy Score': [acc_reg, acc_rfc, acc_dtc]}
df = pd.DataFrame(data)
# Trier les méthodes par ordre décroissant des scores d'exactitude
df = df.sort_values(by='Accuracy Score', ascending=False)
# Créer un graphique à barres horizontales avec Seaborn
plt.figure(figsize=(10, 6))
sns.barplot(x='Accuracy Score', y='Method', data=df, palette='viridis')
plt.xlabel('Accuracy Score')
plt.ylabel('Method')
plt.title('Comparison of Accuracy Scores')
plt.show()
ce graphe nous montre que random forest classifier est la plus éfficace avec une accurancy trés élévée.